package com.learn.project2.service.wx.coupon;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.learn.project2.bean.*;
import com.learn.project2.mapper.MarketCouponMapper;
import com.learn.project2.mapper.MarketCouponUserMapper;
import com.learn.project2.model.vo.wx.coupon.CouponListVO2;
import com.learn.project2.model.vo.wx.coupon.CouponMylistVO2;
import com.learn.project2.model.vo.wx.coupon.CouponSelectListVO2;
import com.learn.project2.service.wx.cart.CartService2;
import com.sun.org.apache.bcel.internal.generic.ARRAYLENGTH;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author 岳子昂
 * @version 1.0
 * @description:
 * @date 2022-01-10 15:22
 */
@Service
public class CouponServiceImpl2 implements CouponService2 {
    @Autowired
    MarketCouponMapper couponMapper;
    @Autowired
    MarketCouponUserMapper couponUserMapper;
    @Autowired
    CartService2 cartService;

    /**
     * @description:
     * @param:
     * @return:
     * @author 岳子昂
     * @date: 2022-01-10 15:40
     */
    @Override
    public CouponListVO2 list(Integer page, Integer limit) {
        // 开启分页信息，会自动在sql语句执行时在后面添加分页的sql语句，并且sql返回结果为page类型
        PageHelper.startPage(page, limit);
        MarketCouponExample example = new MarketCouponExample();
        MarketCouponExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false);

        // 在数据库中查询list
        List<MarketCoupon> marketCoupons = couponMapper.selectByExample(example);

        // 创建vo对象中的list对象
        List<CouponListVO2.ListBean> list = new ArrayList<>();

        // 根据查询结果，为vo list一一赋值
        for (MarketCoupon item : marketCoupons) {
            CouponListVO2.ListBean listBean = new CouponListVO2.ListBean();
            listBean.setId(item.getId());
            listBean.setName(item.getName());
            listBean.setDesc(item.getDesc());
            listBean.setTag(item.getTag());
            listBean.setDiscount(item.getDiscount());
            listBean.setMin(item.getMin());
            listBean.setDays(item.getDays());
            listBean.setStartTime(item.getStartTime());
            listBean.setEndTime(item.getEndTime());

            list.add(listBean);
        }

        PageInfo<MarketCoupon> pageInfo = new PageInfo<>(marketCoupons);
        int total = (int) pageInfo.getTotal();
        int pages = pageInfo.getPages();

        // 创建vo对象，为vo对象一一赋值
        CouponListVO2 vo = new CouponListVO2();

        // 为返回用的vo赋值
        vo.setTotal(total);
        vo.setPages(pages);
        vo.setLimit(limit);
        vo.setPage(page);
        vo.setList(list);

        return vo;
    }

    /**
     * @description:
     * @param:
     * @return:
     * @author 岳子昂
     * @date: 2022-01-10 20:37
     */
    @Override
    public CouponMylistVO2 myList(Short status, Integer page, Integer limit, Integer userId) {

        // 设置pageHelper，会自动在sql语句执行时在后面添加分页的sql语句，并且sql返回结果为page类型
        PageHelper.startPage(page, limit);

        // 根据example从数据库获取相应的值
        MarketCouponUserExample userExample = new MarketCouponUserExample();
        // 根据userId，获取对应的优惠券，因为有些优惠券可以领取多张，所以user表中有多少条记录，就有多少张优惠券
        // pageHelper可以帮助计算total，pages等信息，应该放在根据userID查询语句上面
        MarketCouponUserExample.Criteria UserCriteria = userExample.createCriteria();
        UserCriteria.andUserIdEqualTo(userId).andDeletedEqualTo(false);

        // 利用mapper来查询
        List<MarketCouponUser> marketCouponUsers = couponUserMapper.selectByExample(userExample);

        List<CouponMylistVO2.ListBean> list = new ArrayList<>();


        // 根据优惠券用户列表获取对应的优惠券id，从而根据优惠券id和status，依次查出对应的优惠券，转换为vo中的list
        // 为了避免多张相同的优惠券只会查出一次，所以可以遍历查询，同时遍历转换vo
        for (MarketCouponUser item : marketCouponUsers) {
            // 遍历找出couponId
            Integer couponId = item.getCouponId();

            // 根据couponId和status设置example
            MarketCouponExample example = new MarketCouponExample();
            MarketCouponExample.Criteria criteria = example.createCriteria();
            criteria.andIdEqualTo(couponId).andStatusEqualTo(status).andDeletedEqualTo(false);

            // 根据example查询coupon
            List<MarketCoupon> marketCoupons = couponMapper.selectByExample(example);
            MarketCoupon coupon = marketCoupons.get(0);

            // 根据查出的结果给vo中的listBean赋值
            CouponMylistVO2.ListBean listBean = new CouponMylistVO2.ListBean();
            listBean.setId(item.getId());
            listBean.setCid(couponId);
            listBean.setName(coupon.getName());
            listBean.setDesc(coupon.getDesc());
            listBean.setTag(coupon.getTag());
            listBean.setMin(coupon.getMin());
            listBean.setDiscount(coupon.getDiscount());
            // 开始日期与结束日期只能用user表来取，因为不同人的同种优惠券可能到期日子不同
            listBean.setStartTime(item.getStartTime());
            listBean.setEndTime(item.getEndTime());
            listBean.setAvailable(false);

            // 全部装进去后，把当前的这个bean放入list
            list.add(listBean);
        }

        // pageInfo获取limit和pages
        PageInfo<MarketCouponUser> pageInfo = new PageInfo<>(marketCouponUsers);
        int total = (int) pageInfo.getTotal();
        int pages = pageInfo.getPages();

        CouponMylistVO2 vo = new CouponMylistVO2();
        vo.setTotal(total);
        vo.setPage(pages);
        vo.setLimit(limit);
        vo.setPage(page);
        vo.setList(list);

        return vo;
    }

    /**
     * @description:
     * @param:
     * @return:
     * @author 岳子昂
     * @date: 2022-01-10 23:46
     */
    @Override
    @Transactional
    public int receive(Integer couponId, Integer userId) {

        // 首先查看是否还有剩余购物券 - 根据id查询购物券，如果total等于-1，直接返回 2
        MarketCoupon coupon = couponMapper.selectByPrimaryKey(couponId);
        Integer total = coupon.getTotal();
        if (total == -1) {
            return 2;
        }

        // 获取该优惠券每人可领取的最大限额limit，如果等于0，就直接进行下一步，如果不为0，进行判断：
        Short limit = coupon.getLimit();
        if (limit != null && limit != 0) {
            // 根据couponId 和 用户id查询 该用户所拥有的该优惠券的数量，若数量大于等于limit，直接返回 1
            MarketCouponUserExample example = new MarketCouponUserExample();
            MarketCouponUserExample.Criteria criteria = example.createCriteria();
            criteria.andUserIdEqualTo(userId).andCouponIdEqualTo(couponId);
            List<MarketCouponUser> marketCoupons = couponUserMapper.selectByExample(example);
            // size 就是该用户拥有的优惠券的数量
            int size = marketCoupons.size();
            if (size >= limit) {
                return 1;
            }
        }

        // 到这里说明优惠券有剩余，且该用户还可以领取这张优惠券，就insert coupon-user，同时update优惠券表
        // total 等于1 时，将total更新为-1
        // total 等于0 时，total不变
        // total 等于其他值时，total = total -1

        // insert
        MarketCouponUser user = new MarketCouponUser();
        user.setUserId(userId);
        user.setCouponId(couponId);
        user.setStatus(coupon.getStatus());

        // 判断使用日期类型，0-指定天数 1-指定时间段
        Short timeType = coupon.getTimeType();
        if (timeType == 0){
            Date date = new Date();
            // start time
            user.setStartTime(date);
            // end time
            // 使用日期有多少天，就结束日期就往后延长多少天
            Short days = coupon.getDays();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DATE,days);
            Date endTime = calendar.getTime();
            user.setEndTime(endTime);

        }else if (timeType == 1){
            user.setStartTime(coupon.getStartTime());
            user.setEndTime(coupon.getEndTime());

        }

        user.setAddTime(new Date());
        user.setUpdateTime(new Date());
        user.setDeleted(false);
        couponUserMapper.insertSelective(user);

        // 接下来开始整优惠券表更新
        // update
        if (total == 1) {
            coupon.setTotal(-1);
        } else if (total == 0) {
            // 等于0啥也不干，就还是0
        } else {
            coupon.setTotal(total - 1);
        }

        couponMapper.updateByPrimaryKeySelective(coupon);

        // 全部更新完，返回0
        return 0;
    }

    /**
     * @description:
     * @param:
     * @return:
     * @author 岳子昂
     * @date: 2022-01-11 01:20
     */
    @Override
    @Transactional
    public int exchange(String code, Integer userId) {
        // 首先判断传来的是不是空，是空直接返回失败结果 3
        if (code == null || code.equals("")) {
            return 3;
        }
        // 根据兑换码选取查询优惠券
        MarketCouponExample example = new MarketCouponExample();
        MarketCouponExample.Criteria criteria = example.createCriteria();
        criteria.andCodeEqualTo(code);
        List<MarketCoupon> marketCoupons = couponMapper.selectByExample(example);

        // 若查询出的list长度为0，返回失败结果 3
        if (marketCoupons.size() == 0) {
            return 3;
        }
        // 若优惠券的领取类型不要是根据兑换码获取，返回失败结果 3
        MarketCoupon coupon = marketCoupons.get(0);
        Short type = coupon.getType();
        if (type != 2) {
            return 3;
        }

        // 查询出正常结果，判断该用户是否可以领取
        // total是否足够，若total = -1， 返回失败结果 2
        Integer total = coupon.getTotal();
        if (total == -1) {
            return 2;
        }

        // 根据优惠券id和userId找出该用户所有的该优惠券，与limit对比，如果大于等于limit，返回失败结果 1
        Short limit = coupon.getLimit();
        Integer couponId = coupon.getId();
        if (limit != 0) {
            // 根据couponId 和 用户id查询 该用户所拥有的该优惠券的数量，若数量大于等于limit，直接返回 1
            MarketCouponUserExample userExample = new MarketCouponUserExample();
            MarketCouponUserExample.Criteria userCriteria = userExample.createCriteria();
            userCriteria.andUserIdEqualTo(userId).andCouponIdEqualTo(couponId);
            List<MarketCouponUser> marketCouponUsers = couponUserMapper.selectByExample(userExample);
            // size 就是该用户拥有的优惠券的数量
            int size = marketCouponUsers.size();
            if (size >= limit) {
                return 1;
            }
        }

        // 将该结果放入coupon user表中，并且更新coupon的total值
        // 返回0

        // insert
        MarketCouponUser user = new MarketCouponUser();
        user.setUserId(userId);
        user.setCouponId(couponId);
        user.setStatus(coupon.getStatus());

        // 判断使用日期类型，0-指定天数 1-指定时间段
        Short timeType = coupon.getTimeType();
        if (timeType == 0){
            Date date = new Date();
            // start time
            user.setStartTime(date);
            // end time
            // 使用日期有多少天，就结束日期就往后延长多少天
            Short days = coupon.getDays();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DATE,days);
            Date endTime = calendar.getTime();
            user.setEndTime(endTime);

        }else if (timeType == 1){
            user.setStartTime(coupon.getStartTime());
            user.setEndTime(coupon.getEndTime());

        }

        user.setAddTime(new Date());
        user.setUpdateTime(new Date());
        user.setDeleted(false);
        couponUserMapper.insertSelective(user);

        // update
        if (total == 1) {
            coupon.setTotal(-1);
        } else if (total == 0) {
            // 等于0啥也不干，就还是0
        } else {
            coupon.setTotal(total - 1);
        }

        couponMapper.updateByPrimaryKeySelective(coupon);

        // 全部更新完，返回0
        return 0;
    }

    /**
     * @description:
     * @param:
     * @return:
     * @author 岳子昂
     * @date: 2022-01-11 18:25
     */
    @Override
    public CouponSelectListVO2 selectList(Integer userId, Integer cartId) {
        // 根据userid，拿到该用户现在已有的优惠券
        // 根据example从数据库获取相应的值
        MarketCouponUserExample userExample = new MarketCouponUserExample();
        // 根据userId，获取对应的优惠券，因为有些优惠券可以领取多张，所以user表中有多少条记录，就有多少张优惠券
        MarketCouponUserExample.Criteria UserCriteria = userExample.createCriteria();
        UserCriteria.andUserIdEqualTo(userId).andDeletedEqualTo(false);

        PageHelper.startPage(1, 20);

        // 利用mapper来查询
        List<MarketCouponUser> marketCouponUsers = couponUserMapper.selectByExample(userExample);

        // 创建要传走的vo的list
        ArrayList<CouponSelectListVO2.ListBean> list = new ArrayList<>();


        // 拿到总价，以及现在有的商品种类，为进行下一步的查询作准备
//        int totalPrice = 0;
        BigDecimal price = cartService.getPrice(cartId,userId);
//        List<Integer> goodIds = new ArrayList<>();
        List<MarketCart> carts = cartService.getGoodIds(cartId,userId);
        List<Integer> goodIds = new ArrayList<>();
        for (MarketCart cart : carts) {
            Integer goodsId = cart.getGoodsId();
            goodIds.add(goodsId);
        }

        for (MarketCouponUser item : marketCouponUsers) {
            // 遍历找出couponId
            Integer couponId = item.getCouponId();

            // 1。 商品总价是否高于min
            // 2。 若goodstype != 0，是否有goodsvalue是否包含目前的商品种类
            // 3。 现在的时间是否处于开始时间和结束时间之间
            // 三个条件必须全部满足，才能进行显示 setAvailable(true)

            MarketCouponExample example = new MarketCouponExample();
            MarketCouponExample.Criteria criteria = example.createCriteria();
            criteria.andIdEqualTo(couponId).andDeletedEqualTo(false);
            // 1。 商品总价是否高于min

            // 根据id查的，所以只能查出来一个
            List<MarketCoupon> marketCoupons = couponMapper.selectByExample(example);
            MarketCoupon coupon = marketCoupons.get(0);

            // 根据查出的结果给vo中的listBean赋值
            CouponSelectListVO2.ListBean listBean = new CouponSelectListVO2.ListBean();
            listBean.setId(item.getId());
            listBean.setCid(couponId);
            listBean.setName(coupon.getName());
            listBean.setDesc(coupon.getDesc());
            listBean.setTag(coupon.getTag());
            // 获取使用优惠券的最小值
            BigDecimal min = coupon.getMin();
            listBean.setMin(min);
            listBean.setDiscount(coupon.getDiscount());
            // 开始日期与结束日期只能用user表来取，因为不同人的同种优惠券可能到期日子不同
            Date startTime = item.getStartTime();
            listBean.setStartTime(startTime);
            Date endTime = item.getEndTime();
            listBean.setEndTime(endTime);

            // 默认值设为false，若情况有变，就转换为true
            listBean.setAvailable(false);

            // 1。 商品总价是否高于min
            if (min != null && price != null) {
                // min大于等于price，则不显示，直接将false装入数组
                if (min.compareTo(price) == 1) {
                    list.add(listBean);
                    continue;
                }
            }
            // 2。 若goodstype != 0，是否有goodsvalue是否包含目前的商品种类
            Short goodsType = coupon.getGoodsType();
            if (goodsType != null && goodsType != 0) {
                Integer[] goodsValue = coupon.getGoodsValue();
                // 若两个goods list 有重合，则表示暂时可以用，setAvailable 为 true，可以跳出两goodslist对比的循环
                for (Integer i : goodsValue) {
                    if (i != null && goodIds.contains(i)) {
                        listBean.setAvailable(true);
                        break;
                    }
                }
                // 如果对比完上面的还是无法变为true，说明商品不匹配
                if (listBean.getAvailable() == false) {
                    list.add(listBean);
                    continue;
                }
            }
            // 3。 现在的时间是否处于开始时间和结束时间之间
            // 重新将getAvailable设置为false
            listBean.setAvailable(false);
            Date nowTime = new Date();
            Calendar date = Calendar.getInstance();
            date.setTime(nowTime);

            Calendar begin = Calendar.getInstance();
            begin.setTime(startTime);

            Calendar end = Calendar.getInstance();
            end.setTime(endTime);

            if (date.after(end) || date.before(begin)) {
                list.add(listBean);
                continue;
            }

            // 以上都没拦住时，就是可以展示的
            listBean.setAvailable(true);
            list.add(listBean);
        }

        // pageInfo获取limit和pages
        PageInfo<MarketCouponUser> pageInfo = new PageInfo<>(marketCouponUsers);
        int total = (int) pageInfo.getTotal();
        int pages = pageInfo.getPages();

        CouponSelectListVO2 vo = new CouponSelectListVO2();
        vo.setTotal(total);
        vo.setPages(pages);
        vo.setLimit(total);
        vo.setPage(1);
        vo.setList(list);
        return vo;
    }
}
